package com.consente.demo.netty.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import com.consente.demo.main.Main;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SingleThreadEventLoop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;


@Component
public class NettyServerHandlerTemplate extends ChannelInboundHandlerAdapter {

    //    private NetDevice netDevice;
    private String messageData;
    //    private DataTypeEnum dataType;
    private AtomicBoolean isException = new AtomicBoolean(false);
    //是否是第一条数据，如果是第一条数据，需要判断连接，记录上线日志
    private AtomicBoolean isFirst = new AtomicBoolean(true);

    private static List<ChannelHandlerContext> list = new ArrayList<ChannelHandlerContext>();
    private static final Logger log = LoggerFactory.getLogger(NettyServerHandlerTemplate.class);

    private static final ExecutorService executorService = Executors.newSingleThreadExecutor();

    Main main = new Main();

    int ol = 0;

    /**
     * 指令集合
     */
    private List<String> commandList = new ArrayList<String>();
    private static List<String> nameList = new ArrayList<String>();

    @PostConstruct
    private void initCommandList() {
        commandList.add("010300000006C5C8");
        commandList.add("020300000006C5FB");
        commandList.add("030300000006C42A");
        commandList.add("040300000006C59D");
        nameList.add("0403");
        nameList.add("0303");
        nameList.add("0203");
        nameList.add("0103");
    }

    @PostConstruct
    private void sendCommand() {
        executorService.submit((Runnable) () -> {
            while (true) {
                try {
                    for (int index = 0; index < commandList.size(); index++) {
                        if (!list.isEmpty()) {
                            try {
                                Thread.sleep(5000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            //            while (true){
                            ChannelHandlerContext ctx = list.get(0);
                            byte[] bytes = DatatypeConverter.parseHexBinary(commandList.get(index));
                            ctx.writeAndFlush(Unpooled.wrappedBuffer(bytes));
                            log.info("发送" + commandList.get(index) + "指令成功，等待回应");
                        } else {
                            log.info("无设备发送消息");
                        }
                    }
                    try {
//                    Thread.sleep(180000);
                        Thread.sleep(180000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx){

        if (!list.isEmpty()) {
            log.info("重复链接！");
            ctx.close();
            return;
        } else {
            String b = wFile();
            if("o".equals(b)){
                log.info("文件追加成功");
            }else if("k".equals(b)){
                log.info("文件写入成功");
            }else if("ok".equals(b)){
                log.info("操作成功");
            }else{
                log.info("操作失败");
            }
            list.add(ctx);

        }
    }

    public String wFile(){
        try {
            String now = DateUtil.now();
            String fileName = "deviceLog.log";
            File file = new File("./" + fileName);
            FileOutputStream fos = null;
            if (file.exists()) {
                fos = new FileOutputStream(file,true);
                OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
                log.debug("文件已存在无需创建");
                try {
                    osw.write("设备于"+now+"上线");
                    osw.write("\r\n");
                    osw.flush();
                    osw.close();
                    return "o";
                }catch (IOException e){
                    return "false";
                }
            } else {
                try {
                    file.createNewFile();
                    fos = new FileOutputStream(file);
                    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
                    log.info("文件创建成功，文件名为:" + fileName);
                    osw.write("设备于"+now+"上线\r\n");
                    osw.write("\r\n");
                    osw.flush();
                    osw.close();
                    return "k";
                } catch (IOException e) {
                    return "false";
                }
            }

        }catch (Exception e){
            return "false";
        }
    }

    public boolean DataList(String substring) {
        for (int i = 0; i < nameList.size(); i++) {
            if (substring.equals(nameList.get(i))) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String messageData = objectToHexStr(msg);

        String substring = messageData.substring(0, 4);
        boolean b = DataList(substring);
        if (!b) {
            log.error("恶意链接");
            ctx.close();
            return;
        }
        if (messageData.length() != 34) {
            log.error("恶意链接");
            ctx.close();
            return;
        }
        log.info("收到的数据为：" + messageData);
        String code = main.code(messageData);
        if (code.equals("error")) {
            log.info("校验位错误此次记录不记录");
            return;
        }
        log.info("用电度数为：" + code + "\n+----------------------------------------------------------------------------------------------------------------------+");

        try {
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            super.channelRead(ctx, msg);
            ctx.flush();
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        list.remove(ctx);
        log.error("设备断开连接");

        super.channelInactive(ctx);
    }

    private static String objectToHexStr(Object msg) {
        ByteBuf buf = (ByteBuf) msg;
        byte[] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);//复制内容到字节数组bytes
        return HexUtil.encodeHexStr(bytes);//将接收到的数据转为字符串，此字符串就是客户端发送的字符串
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
//        offlineDevice(netDevice,dataType,"设备端异常",messageData, NetDeviceStatusEnum.OFFLINE,ctx);
    }


}


//
//    /**
//     * 处理设备下线
//     * @param netDevice
//     * @param dataType
//     * @param reason
//     * @param data
//     * @param ctx
//     */
//    private void offlineDevice(NetDevice netDevice,DataTypeEnum dataType,String reason,String data,NetDeviceStatusEnum netDeviceStatus,ChannelHandlerContext ctx){
//        try {
//            deviceStatusHandler.deviceOfflineAndUploadLogAndAlarm(netDevice,dataType,netDeviceStatus,reason,data);
//            isException.set(true);
//        }catch (Exception e){
//            e.printStackTrace();
//        }finally {
//            ctx.close();
//        }
//    }
//
//    private NetDevice checkDataAndGetDtu(String messageData) throws Exception{
//        if(StrUtil.isBlank(messageData)){
//            throw new CustomException("非法数据");
//        }
//        JSONObject dataJson = new JSONObject(messageData);
//        if(dataJson.isEmpty()){
//            throw new CustomException("非法数据");
//        }
//        NetDeviceBO netDeviceBO = netDeviceCache.getByNo(dataJson.getStr("id"));
//        if(netDeviceBO == null){
//            throw new CustomException("未知设备");
//        }
//        NetDevice netDevice = new NetDevice(netDeviceBO);
//        //发送警报
//        DataTypeEnum onlineDataType =DataTypeEnum.getTypeByNetValue(netDevice.getClassifyId());
//        BaseDataAlarmHandler dataAlarmHandler = dataAlarmHandlerFactory.getDataAlarmHandler(onlineDataType.getValue());
//        dataAlarmHandler.simpleAnalyzeDataAndAlarm(netDevice.getNo(),dataJson);
//        return netDevice;
//    }

